<template>
  <div class="app-container">
   <!-- 顶部区域：楼层切换 + 操作按钮 -->
   <div class="page-header">
     <div class="floor-tabs">
       <el-button 
         v-for="floor in floorList" 
         :key="floor.id"
         class="floor-tab"
         :class="{ 
           active: activeFloor === floor.id, 
           'red-dot': floor.hasAlarm
         }"
         @click="handleFloorChange(floor.id)"
       >
         {{ floor.floorName }}
       </el-button>
     </div>
     <div class="header-actions">
       <el-button type="primary" size="small" @click="handleAddFloor">新增楼层</el-button>
       <el-button type="primary" size="small" @click="handleAddRoomGlobal">新增房间</el-button>
     </div>
   </div>

   <!-- 状态图例 -->
   <div class="status-legend">
     <div class="legend-item">
       <svg class="bed-svg svg-free" viewBox="0 0 64 64" fill="currentColor" aria-hidden="true">
         <circle cx="18" cy="18" r="6" />
         <rect x="8" y="24" width="48" height="10" rx="2" />
         <rect x="8" y="34" width="48" height="12" rx="2" />
         <rect x="8" y="46" width="4" height="10" />
         <rect x="52" y="46" width="4" height="10" />
       </svg>
       <span>空闲</span>
     </div>
     <div class="legend-item">
       <svg class="bed-svg svg-occupied" viewBox="0 0 64 64" fill="currentColor" aria-hidden="true">
         <circle cx="18" cy="18" r="6" />
         <rect x="8" y="24" width="48" height="10" rx="2" />
         <rect x="8" y="34" width="48" height="12" rx="2" />
         <rect x="8" y="46" width="4" height="10" />
         <rect x="52" y="46" width="4" height="10" />
       </svg>
       <span>已入住</span>
     </div>
     <div class="legend-item">
       <svg class="bed-svg svg-leave" viewBox="0 0 64 64" fill="currentColor" aria-hidden="true">
         <circle cx="18" cy="18" r="6" />
         <rect x="8" y="24" width="48" height="10" rx="2" />
         <rect x="8" y="34" width="48" height="12" rx="2" />
         <rect x="8" y="46" width="4" height="10" />
         <rect x="52" y="46" width="4" height="10" />
       </svg>
       <span>请假中</span>
     </div>
   </div>

    <!-- 房间卡片 -->
    <div class="room-grid">
     <div 
       v-for="room in filteredRooms" 
       :key="room.id" 
       class="room-card"
       :style="getRoomCardStyle(room)"
     >
       <div class="room-header">
         <div class="room-info">
           <!-- 修改：将已满标签放在房间号右边 -->
           <div class="room-number-wrapper">
             <div class="room-number">房间号：{{ room.roomNo }}</div>
             <div 
               v-if="isBedLimitReached(room)" 
               class="room-full-tag"
               title="床位数量已达上限"
             >
               已满
             </div>
           </div>
           <div class="room-type">房间类型：{{ room.roomType?.roomType || '未设置' }}</div>
           <!-- 新增统计信息组容器 -->
           <div class="room-stats-group">
             <div class="room-stats">总床位：{{ room.totalBeds || 0 }}</div>
             <div class="room-stats">已入住：{{ room.occupiedBeds || 0 }}</div>
             <div class="room-stats">入住率：{{ room.occupancyRate || 0 }}%</div>
           </div>
         </div>
         <div class="room-actions">
           <el-button 
             size="small" 
             plain 
             @click="handleEditRoom(room)"
           >编辑</el-button>
           <el-button 
             size="small" 
             plain 
             :disabled="(room.bedList && room.bedList.length > 0) || false"
             @click="handleDeleteRoom(room)"
           >删除</el-button>
           <el-button 
             size="small" 
             plain 
             @click="handleViewRoom(room)"
           >查看</el-button>
           <!-- 修改：新增床位按钮添加床位数量限制判断 -->
           <el-button 
             size="small" 
             type="primary" 
             :disabled="isBedLimitReached(room)"
             @click="handleAddBed(room)"
           >
             {{ isBedLimitReached(room) ? '床位已满' : '新增床位' }}
           </el-button>
         </div>
       </div>

       <!-- 床位列表 -->
       <div class="bed-list">
         <!-- 实际床位 -->
         <div 
           v-for="bed in sortBeds(room.bedList || [])" 
           :key="bed.id" 
           class="bed-item"
           :class="{ 
             'occupied': bed.status === 1,  
             'leave': bed.status === 2       
           }"
         >
           <div class="bed-card">
             <div class="bed-icon">
               <svg 
                 class="bed-svg"
                 :class="
                   bed.status === 0 ? 'svg-free' : 
                   bed.status === 2 ? 'svg-leave' : 'svg-occupied'
                 "
                 viewBox="0 0 64 64" 
                 fill="currentColor" 
                 aria-hidden="true"
               >
                 <circle cx="18" cy="18" r="6" />
                 <rect x="8" y="24" width="48" height="10" rx="2" />
                 <rect x="8" y="34" width="48" height="12" rx="2" />
                 <rect x="8" y="46" width="4" height="10" />
                 <rect x="52" y="46" width="4" height="10" />
               </svg>
             </div>
             <div class="bed-info">
               <div class="bed-number">床位号：{{ bed.bedNo }}</div>
               <div class="elder-name">老人姓名：{{ bed.elderly?.name || '空闲' }}</div>
               <div class="bed-status">状态：{{ getBedStatusText(bed.status) }}</div>
             </div>
           </div>

           <!-- 床位悬浮操作（编辑/删除）- 已移除状态限制 -->
           <div class="bed-hover-actions">
             <div class="action-btn" @click.stop="handleEditBed(bed)" title="编辑">
               <svg class="action-icon" viewBox="0 0 24 24" fill="currentColor">
                 <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
               </svg>
             </div>
             <div class="action-btn" @click.stop="handleDeleteBed(bed)" title="删除">
               <svg class="action-icon" viewBox="0 0 24 24" fill="currentColor">
                 <path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1z"/>
               </svg>
             </div>
           </div>
         </div>
         
         <!-- 空床位占位符 -->
         <div 
           v-for="index in getEmptyBedSlots(room)" 
           :key="`empty-${index}`" 
           class="bed-item empty-bed-slot"
         >
           <div class="bed-card empty-bed-card">
             <div class="bed-icon">
               <svg 
                 class="bed-svg svg-free"
                 viewBox="0 0 64 64" 
                 fill="currentColor" 
                 aria-hidden="true"
               >
                 <circle cx="18" cy="18" r="6" />
                 <rect x="8" y="24" width="48" height="10" rx="2" />
                 <rect x="8" y="34" width="48" height="12" rx="2" />
                 <rect x="8" y="46" width="4" height="10" />
                 <rect x="52" y="46" width="4" height="10" />
               </svg>
             </div>
             <div class="bed-info">
               <div class="bed-number">空床位</div>
               <div class="elder-name">可安排入住</div>
               <div class="bed-status">状态：空闲</div>
             </div>
           </div>
         </div>
         
         <!-- 空房间提示（当没有任何床位时显示） -->
         <div v-if="!(room.bedList && room.bedList.length) && (!room.totalBeds || room.totalBeds === 0)" class="empty-bed">
           当前房间没有安排床位
         </div>
       </div>
     </div>
   </div>

   <!-- 新增楼层弹窗 -->
   <el-dialog 
     title="新增楼层" 
     v-model="showAddFloorDialog" 
     width="500px"
     :close-on-click-modal="false"
   >
     <el-form :model="addFloorForm" :rules="addFloorRules" ref="addFloorFormRef" label-width="100px">
       <el-form-item label="楼层名称" prop="floorName">
         <el-input v-model="addFloorForm.floorName" placeholder="请输入楼层名称（如：1楼）" maxlength="5" show-word-limit />
       </el-form-item>
       <el-form-item label="排序" prop="sortNo">
         <el-input-number v-model="addFloorForm.sortNo" :min="1" :step="1" />
       </el-form-item>
     </el-form>
     <template #footer>
       <el-button @click="showAddFloorDialog = false">取消</el-button>
       <el-button type="primary" @click="submitAddFloor">确定</el-button>
     </template>
   </el-dialog>

   <!-- 编辑楼层弹窗 -->
   <el-dialog 
     title="编辑楼层" 
     v-model="showEditFloorDialog" 
     width="500px"
     :close-on-click-modal="false"
   >
     <el-form :model="editFloorForm" :rules="editFloorRules" ref="editFloorFormRef" label-width="100px">
       <el-form-item label="楼层名称" prop="floorName">
         <el-input v-model="editFloorForm.floorName" placeholder="请输入楼层名称" maxlength="5" show-word-limit />
       </el-form-item>
       <el-form-item label="排序" prop="sortNo">
         <el-input-number v-model="editFloorForm.sortNo" :min="1" :step="1" />
       </el-form-item>
     </el-form>
     <template #footer>
       <el-button @click="showEditFloorDialog = false">取消</el-button>
       <el-button 
         type="danger" 
         :disabled="!isFloorDeletable"
         @click="submitDeleteFloor"
       >删除</el-button>
       <el-button type="primary" @click="submitEditFloor">确定</el-button>
     </template>
   </el-dialog>

   <!-- 新增/编辑房间弹窗 -->
   <el-dialog 
     :title="isEditRoom ? '编辑房间' : '新增房间'" 
     v-model="showAddRoomDialog" 
     width="500px"
     :close-on-click-modal="false"
   >
     <el-form :model="addRoomForm" :rules="addRoomRules" ref="addRoomFormRef" label-width="100px">
       <el-form-item label="房间号" prop="roomNo">
         <el-input v-model="addRoomForm.roomNo" placeholder="请输入房间号（如：101）" maxlength="5" show-word-limit />
       </el-form-item>
       <el-form-item label="房间类型" prop="roomTypeId">
 <el-select v-model="addRoomForm.roomTypeId" placeholder="请选择房间类型" clearable>
   <el-option 
     v-for="type in roomTypeList" 
     :key="type.id" 
     :label="type.roomType" 
     :value="type.id"       
   />
 </el-select>
</el-form-item>
       <el-form-item label="总床位数" prop="totalBeds">
         <el-input-number 
           v-model="addRoomForm.totalBeds" 
           :min="0" 
           :max="20" 
           :step="1" 
           placeholder="请输入总床位数"
         />
       </el-form-item>
       <el-form-item label="排序" prop="sortNo" v-if="!isEditRoom">
         <el-input-number v-model="addRoomForm.sortNo" :min="1" :step="1" />
       </el-form-item>
       <el-form-item label="所属楼层" prop="floorId" v-if="!isEditRoom">
         <el-select v-model="addRoomForm.floorId" placeholder="请选择楼层" clearable>
           <el-option 
             v-for="floor in floorList" 
             :key="floor.id" 
             :label="floor.floorName" 
             :value="floor.id" 
           />
         </el-select>
       </el-form-item>
     </el-form>
     <template #footer>
       <el-button @click="showAddRoomDialog = false">取消</el-button>
       <el-button type="primary" @click="submitAddRoom">确定</el-button>
     </template>
   </el-dialog>

   <!-- 房间详情弹窗 -->
   <el-dialog 
     title="房间详情" 
     v-model="showRoomDetailDialog" 
     width="800px"
     :close-on-click-modal="false"
   >
     <div class="room-detail">
       <div class="room-detail-header">
         <div class="detail-item">房间号：{{ selectedRoom.roomNo || '-' }}</div>
         <div class="detail-item">房间类型：{{ selectedRoom.roomType?.roomType || '未设置' }}</div>
         <div class="detail-item">总床位数：{{ selectedRoom.totalBeds || 0 }}</div>
         <div class="detail-item">入住床位数：{{ selectedRoom.occupiedBeds || 0 }}</div>
         <div class="detail-item">入住率：{{ selectedRoom.occupancyRate || 0 }}%</div>
         <div class="detail-item">所属楼层：{{ selectedRoom.floor?.floorName || '未设置' }}</div>
       </div>
       <div class="room-detail-table" style="margin-top: 16px;">
         <el-table :data="selectedRoom.bedList || []" border size="small">
           <el-table-column label="床位号" prop="bedNo" align="center" width="100" />
           <el-table-column label="老人姓名" align="center" width="120">
             <template #default="scope">{{ scope.row.elderly?.name || '空闲' }}</template>
           </el-table-column>
           <el-table-column label="老人身份证" align="center" width="180">
             <template #default="scope">{{ scope.row.elderly?.idCard || '-' }}</template>
           </el-table-column>
           <el-table-column label="床位状态" align="center" width="120">
             <template #default="scope">{{ getBedStatusText(scope.row.status) }}</template>
           </el-table-column>
           <el-table-column label="护理等级" align="center" width="140">
             <template #default="scope">
               {{ scope.row.elderly?.checkInManagementList?.[0]?.nursingLevel?.levelName || '-' }}
             </template>
           </el-table-column>
           <el-table-column label="入住时间" align="center" width="180">
             <template #default="scope">
               {{ scope.row.elderly?.checkInManagementList?.[0]?.checkInStartTime || '-' }}
             </template>
           </el-table-column>
         </el-table>
       </div>
     </div>
     <template #footer>
       <el-button @click="showRoomDetailDialog = false">关闭</el-button>
     </template>
   </el-dialog>

   <!-- 新增/编辑床位弹窗 -->
   <el-dialog 
     :title="isEditBed ? '编辑床位' : '新增床位'" 
     v-model="showAddBedDialog" 
     width="500px"
     :close-on-click-modal="false"
   >
     <el-form :model="addBedForm" :rules="addBedRules" ref="addBedFormRef" label-width="100px">
       <el-form-item label="床位号" prop="bedNo">
         <el-input v-model="addBedForm.bedNo" placeholder="请输入床位号（如：101-1）" maxlength="10" show-word-limit />
       </el-form-item>
       <el-form-item label="排序" prop="sortNo" v-if="!isEditBed">
         <el-input-number v-model="addBedForm.sortNo" :min="1" :step="1" />
       </el-form-item>
       <el-form-item label="所属房间" prop="roomId" v-if="!isEditBed">
         <el-select v-model="addBedForm.roomId" placeholder="请选择房间" disabled>
           <el-option 
             :label="currentRoomForBed.roomNo || '未选择'" 
             :value="currentRoomForBed.id || 0" 
           />
         </el-select>
       </el-form-item>
       <el-form-item label="床位状态" prop="status" v-if="isEditBed">
         <el-select v-model="addBedForm.status" placeholder="请选择床位状态" clearable>
           <el-option label="空闲" value="0" />
           <el-option label="已入住" value="1" />
           <el-option label="请假中" value="2" />
         </el-select>
       </el-form-item>
     </el-form>
     <template #footer>
       <el-button @click="showAddBedDialog = false">取消</el-button>
       <el-button type="primary" @click="submitAddBed">确定</el-button>
     </template>
   </el-dialog>
 </div>
</template>

<script setup name="RoomManagement">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
// 导入接口 - 完全符合您的roomManage.js接口命名规范
import { 
 // 楼层相关
 listFloor, getFloor, addFloor, updateFloor, delFloor,
 listFloorAllRelations, getFloorRelationsById,
 
 // 房间相关
 listRoom, getRoom, addRoom, updateRoom, delRoom,
 
 // 床位相关
 listBed, getBed, addBed, updateBed, delBed,
 
 // 房型相关
 listType
} from '@/api/system/roomManage'

// -------------------------- 消息队列管理 --------------------------
let messageQueue = []
let isShowingMessage = false

/**
 * 统一消息显示方法
 * @param {string} message - 消息内容
 * @param {string} type - 消息类型: success/error/warning/info
 */
const showMessage = (message, type = 'info') => {
  messageQueue.push({ message, type })
  
  if (!isShowingMessage) {
    processMessageQueue()
  }
}

/**
 * 处理消息队列
 */
const processMessageQueue = () => {
  if (messageQueue.length === 0) {
    isShowingMessage = false
    return
  }
  
  isShowingMessage = true
  const { message, type } = messageQueue.shift()
  
  ElMessage({
    message,
    type,
    duration: 3000,
    onClose: () => {
      setTimeout(() => {
        processMessageQueue()
      }, 300)
    }
  })
}

// -------------------------- 基础数据定义 --------------------------
const floorList = ref([])
const activeFloor = ref(0)
const roomList = ref([])
const roomTypeList = ref([])
// 弹窗状态
const showAddFloorDialog = ref(false)
const showEditFloorDialog = ref(false)
const showAddRoomDialog = ref(false)
const showRoomDetailDialog = ref(false)
const showAddBedDialog = ref(false)
// 编辑标记
const isEditRoom = ref(false)
const isEditBed = ref(false)
// 当前操作的房间
const currentRoomForBed = ref({ id: 0, roomNo: '' })
// 选中的房间（详情用）
const selectedRoom = ref({ 
 roomNo: '', 
 roomType: {}, 
 totalBeds: 0, 
 occupiedBeds: 0, 
 occupancyRate: 0, 
 floor: {}, 
 bedList: [] 
})
// 楼层删除状态（是否有房间）
const isFloorDeletable = ref(false)

// -------------------------- 表单数据 --------------------------
const addFloorForm = reactive({
 floorName: '',
 sortNo: 1,
 isDeleted: 0
})
const editFloorForm = reactive({
 id: 0,
 floorName: '',
 sortNo: 1
})
const addRoomForm = reactive({
 id: 0,
 roomNo: '',
 roomTypeId: null,
 floorId: null,
 sortNo: 1,
 isDeleted: 0,
 totalBeds: 0 // 新增totalBeds字段绑定
})
const addBedForm = reactive({
 id: 0,
 bedNo: '',
 roomId: 0,
 sortNo: 1,
 status: 0,
 isDeleted: 0
})

// -------------------------- 先定义校验函数 --------------------------
// 唯一性验证函数（必须在验证规则之前定义）
const validateUniqueFloorName = async (rule, value, callback) => {
 if (!value) {
   callback()
   return
 }
 
 try {
   const params = { floorName: value }
   if (showEditFloorDialog.value) params.id = editFloorForm.id
   
   const res = await listFloor(params)
   console.log('楼层名称验证响应:', res)
   
   if (res.code === 200) {
     // 安全地检查数据长度
     const dataLength = res.data && Array.isArray(res.data) ? res.data.length : 0
     if (dataLength > 0) {
       callback(new Error('楼层名称已存在'))
     } else {
       callback()
     }
   } else {
     callback()
   }
 } catch (error) {
   console.error('楼层名称验证错误:', error)
   callback()
 }
}

const validateUniqueRoomNo = async (rule, value, callback) => {
 if (!value) {
   callback()
   return
 }
 
 try {
   const params = { roomNo: value, floorId: addRoomForm.floorId }
   if (isEditRoom.value) params.id = addRoomForm.id
   
   const res = await listRoom(params)
   console.log('房间号验证响应:', res)
   
   if (res.code === 200) {
     const dataLength = res.data && Array.isArray(res.data) ? res.data.length : 0
     if (dataLength > 0) {
       callback(new Error('房间号已存在'))
     } else {
       callback()
     }
   } else {
     callback()
   }
 } catch (error) {
   console.error('房间号验证错误:', error)
   callback()
 }
}

const validateUniqueBedNo = async (rule, value, callback) => {
 if (!value) {
   callback()
   return
 }
 
 try {
   const params = { bedNo: value, roomId: addBedForm.roomId }
   if (isEditBed.value) params.id = addBedForm.id
   
   const res = await listBed(params)
   console.log('床位号验证响应:', res)
   
   if (res.code === 200) {
     const dataLength = res.data && Array.isArray(res.data) ? res.data.length : 0
     if (dataLength > 0) {
       callback(new Error('床位号已存在'))
     } else {
       callback()
     }
   } else {
     callback()
   }
 } catch (error) {
   console.error('床位号验证错误:', error)
   callback()
 }
}

// -------------------------- 再定义表单验证规则 --------------------------
const addFloorRules = reactive({
 floorName: [
   { required: true, message: '请输入楼层名称（如：1楼）', trigger: 'blur' },
   { max: 5, message: '楼层名称最多5个字符', trigger: 'blur' },
   { validator: validateUniqueFloorName, trigger: 'blur' }
 ],
 sortNo: [{ required: true, message: '请输入排序号（最小1）', trigger: 'change' }]
})
const editFloorRules = reactive({
 floorName: [
   { required: true, message: '请输入楼层名称', trigger: 'blur' },
   { max: 5, message: '楼层名称最多5个字符', trigger: 'blur' },
   { validator: validateUniqueFloorName, trigger: 'blur' }
 ],
 sortNo: [{ required: true, message: '请输入排序号', trigger: 'change' }]
})
const addRoomRules = reactive({
 roomNo: [
   { required: true, message: '请输入房间号（如：101）', trigger: 'blur' },
   { max: 5, message: '房间号最多5个字符', trigger: 'blur' },
   { validator: validateUniqueRoomNo, trigger: 'blur' }
 ],
 roomTypeId: [{ required: true, message: '请选择房间类型', trigger: 'change' }],
 floorId: [{ required: true, message: '请选择所属楼层', trigger: 'change' }],
 sortNo: [{ required: true, message: '请输入排序号', trigger: 'change' }],
 totalBeds: [{ required: true, message: '请输入总床位数', trigger: 'change' }] // 新增总床位数校验
})
const addBedRules = reactive({
 bedNo: [
   { required: true, message: '请输入床位号（如：101-1）', trigger: 'blur' },
   { max: 10, message: '床位号最多10个字符', trigger: 'blur' },
   { validator: validateUniqueBedNo, trigger: 'blur' }
 ],
 sortNo: [{ required: true, message: '请输入排序号', trigger: 'change' }],
 status: [{ required: isEditBed.value, message: '请选择床位状态', trigger: 'change' }]
})

// -------------------------- 表单引用 --------------------------
const addFloorFormRef = ref(null)
const editFloorFormRef = ref(null)
const addRoomFormRef = ref(null)
const addBedFormRef = ref(null)

// -------------------------- 计算属性 --------------------------
const filteredRooms = computed(() => {
 return roomList.value.filter(room => room.floorId === activeFloor.value)
})

// -------------------------- 页面加载初始化 --------------------------
onMounted(async () => {
 try {
   await Promise.all([
     loadFloorList(),
     loadRoomTypeList()
   ])
 } catch (error) {
   showMessage('页面初始化失败：' + (error.message || '网络异常'), 'error')
 }
})

// -------------------------- 数据加载方法 --------------------------
/** 加载楼层列表 */
const loadFloorList = async () => {
 try {
   const res = await listFloorAllRelations()
   console.log('楼层列表响应:', res)
   
   if (res.code === 200 && Array.isArray(res.data)) {
     // 按照楼层名称中的数字大小排序
     floorList.value = res.data.sort((a, b) => {
       // 提取楼层名称中的数字
       const numA = parseInt(a.floorName.replace(/\D/g, '')) || 0
       const numB = parseInt(b.floorName.replace(/\D/g, '')) || 0
       return numA - numB
     })
     if (floorList.value.length > 0) {
       activeFloor.value = floorList.value[0].id
       await loadRoomListByFloor(activeFloor.value)
     }
   } else {
     showMessage('未查询到楼层数据', 'warning')
   }
 } catch (error) {
   console.error('加载楼层错误:', error)
   showMessage('加载楼层失败：' + (error.message || '接口调用异常'), 'error')
 }
}

const loadRoomTypeList = async () => {
 try {
   // 传递pageNum=1和足够大的pageSize，获取所有数据
   const res = await listType({ 
     status: 1, 
     pageNum: 1,    // 第一页
     pageSize: 1000 // 足够大的每页条数，覆盖所有数据
   })
   console.log('房型列表响应:', res)
   
   if (res.code === 200 && Array.isArray(res.rows)) {
     roomTypeList.value = res.rows.map(item => ({
       id: item.id,
       roomType: item.roomType // 已修正的字段映射
     }))
   } else {
     showMessage('未查询到房型数据', 'warning')
   }
 } catch (error) {
   console.error('加载房型错误:', error)
   showMessage('加载房型失败：' + (error.message || '接口调用异常'), 'error')
 }
}


/** 根据楼层ID加载房间列表 + 计算删除状态 */
const loadRoomListByFloor = async (floorId) => {
 try {
   const res = await getFloorRelationsById(floorId)
   console.log('房间列表响应:', res)
   
   if (res.code === 200 && res.data) {
     const targetFloor = res.data
     const rooms = targetFloor.roomList || []
     // 计算房间的床位统计
     roomList.value = rooms.map(room => {
       const bedList = room.bedList || []
       const totalBeds = room.totalBeds || 0 // 从room表的total_beds字段取值
       const occupiedBeds = bedList.filter(bed => bed.status === 1 || bed.status === 2).length
       const occupancyRate = totalBeds === 0 ? 0 : Math.round((occupiedBeds / totalBeds) * 100)
       return { ...room, totalBeds, occupiedBeds, occupancyRate }
     })
     // 判断楼层是否可删除（无房间时可删）
     isFloorDeletable.value = rooms.length === 0
   } else {
     roomList.value = []
     showMessage('该楼层未查询到房间数据', 'warning')
     isFloorDeletable.value = true
   }
 } catch (error) {
   console.error('加载房间错误:', error)
   roomList.value = []
   showMessage('加载房间失败：' + (error.message || '接口调用异常'), 'error')
   isFloorDeletable.value = true
 }
}

// 监听楼层变化，重新加载房间和删除状态
watch(activeFloor, async (newVal) => {
 await loadRoomListByFloor(newVal)
})

// -------------------------- 新增方法：床位数量限制判断 --------------------------
/** 
* 判断房间的床位数量是否已达到上限
* 条件：已入住床位数 >= 房间的totalBeds限制
*/
const isBedLimitReached = (room) => {
 if (!room) return false
 
 const occupiedBeds = room.occupiedBeds || 0
 const maxBeds = room.totalBeds || 0
 
 return occupiedBeds >= maxBeds
}

// -------------------------- 新增方法：空床位占位符计算 --------------------------
/** 
* 计算需要显示的空床位占位符数量
* 根据总床位数和实际床位数计算差值
*/
const getEmptyBedSlots = (room) => {
 if (!room) return 0
 
 const totalBeds = room.totalBeds || 0
 const actualBeds = room.bedList ? room.bedList.length : 0
 const emptySlots = totalBeds - actualBeds
 
 return Math.max(0, emptySlots)
}

/** 
* 根据房间总床位数动态设置房间卡片高度
* 确保所有房间卡片高度一致，布局整齐
*/
const getRoomCardStyle = (room) => {
 const totalBeds = room.totalBeds || 0
 // 根据床位数计算最小高度，确保布局整齐
 const minHeight = 180 + Math.ceil(totalBeds / 2) * 90 // 基础高度 + 床位行数 * 每行高度
 return {
   minHeight: `${minHeight}px`
 }
}

// -------------------------- 事件处理方法 --------------------------
/** 切换楼层 */
const handleFloorChange = async (floorId) => {
 if (activeFloor.value === floorId) return
 activeFloor.value = floorId
}

/** 新增楼层 */
const handleAddFloor = () => {
 addFloorForm.floorName = ''
 // 自动计算下一个排序号：当前最大sortNo + 1
 const maxSortNo = floorList.value.length > 0 
   ? Math.max(...floorList.value.map(f => f.sortNo || 0))
   : 0
 addFloorForm.sortNo = maxSortNo + 1
 addFloorFormRef.value?.clearValidate()
 showAddFloorDialog.value = true
}

/** 编辑楼层 */
const handleEditFloor = async (floor) => {
 try {
   const res = await getFloor(floor.id)
   console.log('编辑楼层详情响应:', res)
   
   if (res.code === 200 && res.data) {
     editFloorForm.id = res.data.id
     editFloorForm.floorName = res.data.floorName
     editFloorForm.sortNo = res.data.sortNo || 1
     editFloorFormRef.value?.clearValidate()
     showEditFloorDialog.value = true
   }
 } catch (error) {
   console.error('获取楼层详情错误:', error)
   showMessage('获取楼层详情失败：' + (error.message || '接口异常'), 'error')
 }
}

/** 新增房间（顶部按钮） */
const handleAddRoomGlobal = () => {
 isEditRoom.value = false
 addRoomForm.id = 0
 addRoomForm.roomNo = ''
 addRoomForm.roomTypeId = null
 addRoomForm.floorId = activeFloor.value
 addRoomForm.sortNo = 1
 addRoomForm.totalBeds = 0 // 初始化总床位数
 addRoomFormRef.value?.clearValidate()
 showAddRoomDialog.value = true
}

/** 编辑房间 */
const handleEditRoom = async (room) => {
 try {
   const res = await getRoom(room.id)
   console.log('编辑房间详情响应:', res)
   
   if (res.code === 200 && res.data) {
     isEditRoom.value = true
     addRoomForm.id = res.data.id
     addRoomForm.roomNo = res.data.roomNo
     addRoomForm.roomTypeId = res.data.roomTypeId
     addRoomForm.floorId = res.data.floorId
     addRoomForm.sortNo = res.data.sortNo || 1
     addRoomForm.totalBeds = res.data.totalBeds || 0 // 回显总床位数
     addRoomFormRef.value?.clearValidate()
     showAddRoomDialog.value = true
   }
 } catch (error) {
   console.error('获取房间详情错误:', error)
   showMessage('获取房间详情失败：' + (error.message || '接口异常'), 'error')
 }
}

/** 删除房间（校验床位关联） */
const handleDeleteRoom = async (room) => {
 try {
   await ElMessageBox.confirm(
     `确定删除房间【${room.roomNo}】吗？删除后不可恢复！`,
     '删除确认',
     { type: 'warning', draggable: true }
   )
   const res = await delRoom(room.id)
   console.log('删除房间响应:', res)
   
   if (res.code === 200) {
     showMessage('删除房间成功', 'success')
     await loadRoomListByFloor(activeFloor.value)
   } else {
     showMessage(res.msg || '删除房间失败', 'error')
   }
 } catch (error) {
   if (error === 'cancel') return
   console.error('删除房间错误:', error)
   showMessage('删除房间失败：' + (error.message || '接口异常'), 'error')
 }
}

/** 查看房间详情 */
const handleViewRoom = (room) => {
 selectedRoom.value = JSON.parse(JSON.stringify(room))
 showRoomDetailDialog.value = true
}

/** 新增床位 - 添加限制检查 */
const handleAddBed = (room) => {
 // 再次检查床位限制（防止在点击时状态发生变化）
 if (isBedLimitReached(room)) {
   showMessage(`房间 ${room.roomNo} 的床位数量已达到上限（${room.totalBeds}个），无法新增床位`, 'warning')
   return
 }
 
 isEditBed.value = false
 currentRoomForBed.value = { id: room.id, roomNo: room.roomNo }
 addBedForm.id = 0
 addBedForm.bedNo = ''
 addBedForm.roomId = room.id
 addBedForm.sortNo = 1
 addBedForm.status = 0
 addBedFormRef.value?.clearValidate()
 showAddBedDialog.value = true
}

/** 编辑床位 */
const handleEditBed = async (bed) => {
 try {
   const res = await getBed(bed.id)
   console.log('编辑床位详情响应:', res)
   
   if (res.code === 200 && res.data) {
     isEditBed.value = true
     addBedForm.id = res.data.id
     addBedForm.bedNo = res.data.bedNo
     addBedForm.roomId = res.data.roomId
     addBedForm.sortNo = res.data.sortNo || 1
     addBedForm.status = res.data.status || 0
     // 回显所属房间
     const room = roomList.value.find(r => r.id === res.data.roomId)
     if (room) currentRoomForBed.value = { id: room.id, roomNo: room.roomNo }
     addBedFormRef.value?.clearValidate()
     showAddBedDialog.value = true
   }
 } catch (error) {
   console.error('获取床位详情错误:', error)
   showMessage('获取床位详情失败：' + (error.message || '接口异常'), 'error')
 }
}

/** 删除床位（校验老人关联） */
const handleDeleteBed = async (bed) => {
 try {
   await ElMessageBox.confirm(
     `确定删除床位【${bed.bedNo}】吗？删除后不可恢复！`,
     '删除确认',
     { type: 'warning', draggable: true }
   )
   const res = await delBed(bed.id)
   console.log('删除床位响应:', res)
   
   if (res.code === 200) {
     showMessage('删除床位成功', 'success')
     await loadRoomListByFloor(activeFloor.value)
   } else {
     showMessage(res.msg || '删除床位失败', 'error')
   }
 } catch (error) {
   if (error === 'cancel') return
   console.error('删除床位错误:', error)
   showMessage('删除床位失败：' + (error.message || '接口异常'), 'error')
 }
}

// -------------------------- 表单提交方法 --------------------------
/** 提交新增楼层 */
const submitAddFloor = async () => {
 const form = addFloorFormRef.value
 if (!form) return
 
 try {
   // 表单验证
   const valid = await form.validate()
   if (!valid) {
     console.log('表单验证失败')
     return
   }
   
   console.log('提交新增楼层数据:', addFloorForm)
   
   const res = await addFloor(addFloorForm)
   console.log('新增楼层响应:', res)
   
   if (res.code === 200) {
     showMessage('新增楼层成功', 'success')
     showAddFloorDialog.value = false
     await loadFloorList()
   } else {
     showMessage(res.msg || '新增楼层失败', 'error')
   }
 } catch (error) {
   console.error('新增楼层错误:', error)
   // 表单验证失败会抛出异常,直接返回,不显示错误提示(因为表单已经显示了错误信息)
   if (error && typeof error === 'object' && 'message' in error) {
     // 如果是接口调用失败,显示错误提示
     showMessage('新增楼层失败：' + (error.message || '接口异常'), 'error')
   }
   // 表单验证失败时,直接返回,不做任何提示
   return
 }
}

/** 提交编辑楼层 */
const submitEditFloor = async () => {
 const form = editFloorFormRef.value
 if (!form) return
 
 try {
   // 表单验证
   const valid = await form.validate()
   if (!valid) {
     console.log('表单验证失败')
     return
   }
   
   console.log('提交编辑楼层数据:', editFloorForm)
   
   const res = await updateFloor(editFloorForm)
   console.log('编辑楼层响应:', res)
   
   if (res.code === 200) {
     showMessage('编辑楼层成功', 'success')
     showEditFloorDialog.value = false
     await loadFloorList()
   } else {
     showMessage(res.msg || '编辑楼层失败', 'error')
   }
 } catch (error) {
   console.error('编辑楼层错误:', error)
   // 表单验证失败会抛出异常,直接返回,不显示错误提示(因为表单已经显示了错误信息)
   if (error && typeof error === 'object' && 'message' in error) {
     // 如果是接口调用失败,显示错误提示
     showMessage('编辑楼层失败：' + (error.message || '接口异常'), 'error')
   }
   // 表单验证失败时,直接返回,不做任何提示
   return
 }
}

/** 提交删除楼层（校验房间关联） */
const submitDeleteFloor = async () => {
 try {
   await ElMessageBox.confirm(
     `确定删除楼层【${editFloorForm.floorName}】吗？会删除该楼层下所有房间！`,
     '危险操作',
     { type: 'error', draggable: true }
   )
   const res = await delFloor(editFloorForm.id)
   console.log('删除楼层响应:', res)
   
   if (res.code === 200) {
     showMessage('删除楼层成功', 'success')
     showEditFloorDialog.value = false
     await loadFloorList()
   } else {
     showMessage(res.msg || '删除楼层失败', 'error')
   }
 } catch (error) {
   if (error === 'cancel') return
   console.error('删除楼层错误:', error)
   showMessage('删除楼层失败：' + (error.message || '接口异常'), 'error')
 }
}

/** 提交新增/编辑房间 */
const submitAddRoom = async () => {
 const form = addRoomFormRef.value
 if (!form) return
 
 try {
   await form.validate()
   console.log('提交房间数据:', addRoomForm)
   
   const res = isEditRoom.value 
     ? await updateRoom(addRoomForm) 
     : await addRoom(addRoomForm)
   
   console.log('房间操作响应:', res)
   
   if (res.code === 200) {
     showMessage(isEditRoom.value ? '编辑房间成功' : '新增房间成功', 'success')
     showAddRoomDialog.value = false
     await loadRoomListByFloor(activeFloor.value)
   } else {
     showMessage(res.msg || `${isEditRoom.value ? '编辑' : '新增'}房间失败`, 'error')
   }
 } catch (error) {
   console.error('房间操作错误:', error)
   if (error.name !== 'Error') return
   showMessage(`${isEditRoom.value ? '编辑' : '新增'}房间失败：` + (error.message || '接口异常'), 'error')
 }
}

/** 提交新增/编辑床位 */
const submitAddBed = async () => {
 const form = addBedFormRef.value
 if (!form) return
 
 try {
   await form.validate()
   console.log('提交床位数据:', addBedForm)
   
   const res = isEditBed.value 
     ? await updateBed(addBedForm) 
     : await addBed(addBedForm)
   
   console.log('床位操作响应:', res)
   
   if (res.code === 200) {
     showMessage(isEditBed.value ? '编辑床位成功' : '新增床位成功', 'success')
     showAddBedDialog.value = false
     await loadRoomListByFloor(activeFloor.value)
   } else {
     showMessage(res.msg || `${isEditBed.value ? '编辑' : '新增'}床位失败`, 'error')
   }
 } catch (error) {
   console.error('床位操作错误:', error)
   if (error.name !== 'Error') return
   showMessage(`${isEditBed.value ? '编辑' : '新增'}床位失败：` + (error.message || '接口异常'), 'error')
 }
}

// -------------------------- 工具方法 --------------------------
/** 床位排序（按sortNo升序） */
const sortBeds = (beds) => {
 return [...beds].sort((a, b) => {
   const sa = typeof a.sortNo === 'number' ? a.sortNo : 999
   const sb = typeof b.sortNo === 'number' ? b.sortNo : 999
   return sa - sb
 })
}

/** 床位状态转文字 */
const getBedStatusText = (status) => {
 switch (status) {
   case 0: return '空闲'
   case 1: return '已入住'
   case 2: return '请假中'
   default: return '未知状态'
 }
}
</script>

<style scoped>
/* 样式部分与原代码一致，无修改 */
.app-container {
 padding: 20px;
 height: 100vh;
 overflow: auto;
 background-color: #fafafa;
 box-sizing: border-box;
}

.page-header {
 display: flex;
 align-items: center;
 justify-content: space-between;
 margin-bottom: 16px;
 flex-wrap: wrap;
 gap: 10px;
}
.floor-tabs {
 display: flex;
 gap: 8px;
 flex-wrap: wrap;
}
.header-actions {
 display: flex;
 gap: 8px;
}

.status-legend {
 display: flex;
 align-items: center;
 gap: 20px;
 margin-bottom: 16px;
 color: #666;
 font-size: 12px;
 flex-wrap: wrap;
}
.legend-item {
 display: flex;
 align-items: center;
 gap: 6px;
}

.room-grid {
 display: grid;
 grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
 gap: 16px;
}
.room-card {
 border: 1px solid #ebeef5;
 border-radius: 8px;
 overflow: hidden;
 background-color: #fff;
 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
 transition: box-shadow 0.2s;
}
.room-card:hover {
 box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.room-header {
 display: flex;
 justify-content: space-between;
 align-items: flex-start;
 padding: 12px 16px;
 background-color: #f5f7fa;
 border-bottom: 1px solid #ebeef5;
}
.room-info {
 display: flex;
 flex-direction: column;
 gap: 2px;
}

/* 新增：房间号包装器，用于并排显示房间号和已满标签 */
.room-number-wrapper {
 display: flex;
 align-items: center;
 gap: 8px;
}

.room-number {
 font-size: 14px;
 font-weight: 500;
 color: #333;
}

/* 修改：已满标签样式 */
.room-full-tag {
 font-size: 10px;
 color: #f56c6c;
 background-color: #fef0f0;
 padding: 2px 6px;
 border-radius: 10px;
 border: 1px solid #fbc4c4;
 font-weight: 500;
 white-space: nowrap;
}

.room-type, .room-stats {
 font-size: 12px;
 color: #666;
}

/* 新增楼层Tab样式 */
.floor-tabs {
 display: flex;
 margin-bottom: 20px;
 gap: 4px;
}

.floor-tab {
 padding: 8px 16px;
 background-color: #e5e7eb;
 border: none;
 cursor: pointer;
 border-radius: 4px 4px 0 0;
 font-size: 14px;
 transition: all 0.2s;
}

.floor-tab.active {
 background-color: #fff;
 font-weight: bold;
 box-shadow: 0 -2px 0 0 #42b983 inset;
}

/* 新增：统计信息组的行内布局 */
.room-stats-group {
 display: flex;
 flex-direction: row;
 gap: 12px;
 align-items: center;
}

/* 保持单个统计项的样式 */
.room-stats {
 font-size: 12px;
 color: #666;
 white-space: nowrap;
}

.room-actions {
 display: grid;
 grid-template-columns: repeat(2, minmax(60px, 1fr));
 gap: 6px;
 justify-items: end;
 width: fit-content;
 margin-left: auto;
}

.room-actions :deep(.el-button--small) {
 width: 100%;
 box-sizing: border-box;
 min-width: 60px;
 padding: 2px 6px;
 font-size: 12px;
 height: 24px;
 line-height: 20px;
}

.bed-list {
 padding: 16px;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 gap: 12px;
}
.bed-item {
 position: relative;
}
.bed-card {
 display: flex;
 align-items: center;
 padding: 12px;
 border: 1px solid #ebeef5;
 border-radius: 6px;
 background-color: #fff;
 transition: all 0.2s;
}
.bed-item:hover .bed-card {
 border-color: #409eff;
 box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}
.bed-item.occupied .bed-card {
 background-color: #f0f9eb;
 border-color: #c2e7b0;
}
.bed-item.leave .bed-card {
 background-color: #fef7e0;
 border-color: #ffe58f;
}

/* 新增：空床位占位符样式 */
.empty-bed-slot .bed-card {
 background-color: #fafafa;
 border: 1px dashed #dcdfe6;
 opacity: 0.6;
}
.empty-bed-slot .bed-card:hover {
 border-color: #c0c4cc;
 box-shadow: none;
}
.empty-bed-slot .elder-name,
.empty-bed-slot .bed-status {
 color: #c0c4cc;
}

.bed-icon {
 width: 36px;
 height: 36px;
 display: flex;
 align-items: center;
 justify-content: center;
 margin-right: 12px;
}
.bed-svg {
 width: 24px;
 height: 24px;
}
.svg-free { color: #c0c4cc; }
.svg-occupied { color: #67c23a; }
.svg-leave { color: #e6a23c; }

.bed-info {
 flex: 1;
 display: flex;
 flex-direction: column;
 gap: 4px;
}
.bed-number, .elder-name, .bed-status {
 font-size: 12px;
 color: #666;
}
.bed-number {
 font-weight: 500;
 color: #333;
}

.bed-hover-actions {
 position: absolute;
 top: 8px;
 right: 8px;
 display: none;
 align-items: center;
 gap: 6px;
 background-color: rgba(0, 0, 0, 0.5);
 border-radius: 4px;
 padding: 4px;
 z-index: 10;
}
.bed-item:hover .bed-hover-actions {
 display: flex;
}
.action-btn {
 width: 24px;
 height: 24px;
 display: flex;
 align-items: center;
 justify-content: center;
 cursor: pointer;
 border-radius: 4px;
 transition: background-color 0.2s;
}
.action-btn:hover {
 background-color: rgba(255, 255, 255, 0.2);
}
.action-icon {
 width: 16px;
 height: 16px;
 color: #fff;
}

.empty-bed {
 grid-column: 1 / -1;
 text-align: center;
 padding: 30px 0;
 color: #999;
 font-size: 12px;
 border: 1px dashed #ebeef5;
 border-radius: 6px;
 background-color: #fafafa;
}

.room-detail {
 padding: 8px 0;
}
.room-detail-header {
 display: flex;
 flex-wrap: wrap;
 gap: 16px;
 margin-bottom: 16px;
 padding-bottom: 12px;
 border-bottom: 1px solid #ebeef5;
}
.detail-item {
 font-size: 13px;
 color: #666;
 display: flex;
 align-items: center;
 gap: 4px;
}
.detail-item::before {
 content: '';
 width: 4px;
 height: 4px;
 border-radius: 50%;
 background-color: #409eff;
}
.room-detail-table .el-table {
 font-size: 12px;
}
.room-detail-table .el-table__header th {
 background-color: #f5f7fa;
 font-weight: 500;
}

@media (max-width: 768px) {
 .room-grid {
   grid-template-columns: 1fr;
 }
 .bed-list {
   grid-template-columns: 1fr;
 }
 .status-legend {
   gap: 12px;
 }
 .page-header {
   flex-direction: column;
   align-items: flex-start;
 }
}
</style>